package object_pool

import (
	"errors"
	"time"
)

type ReuseableObj struct{}

type ObjPool struct {
	bufChan chan *ReuseableObj
}

func NewObjPool(numOfObj int) *ObjPool {
	objPool := ObjPool{}
	objPool.bufChan = make(chan *ReuseableObj, numOfObj)
	for i := 0; i < numOfObj; i++ {
		objPool.bufChan <- &ReuseableObj{}
	}
	return &objPool
}

func (p *ObjPool) GetObj(timeout time.Duration) (*ReuseableObj, error) {
	select {
	case ret := <-p.bufChan:
		return ret, nil
		//设计原则：slow response比quick fail更具备伤害力
	case <-time.After(timeout): //超时控制，如果pool中对象被用完了，在timeout时间内，没有对象被释放，则报 "timeout" 错误
		return nil, errors.New("time out")
	}
}

func (p *ObjPool) ReleaseObj(obj *ReuseableObj) error {
	select {
	case p.bufChan <- obj: //如果能立即放入，则释放成功；否则被阻塞，表示池已满，抛出“overflow“错误
		return nil
	default:
		return errors.New("overflow")
	}
}
